/* IO Related Functions */
/* returns the contents of a file */
TailsNS.getContents = function(aURL, charset){
  if( !charset ) {
    charset = "UTF-8"
  }
  var ioService=Components.classes["@mozilla.org/network/io-service;1"]
    .getService(Components.interfaces.nsIIOService);
  var scriptableStream=Components
    .classes["@mozilla.org/scriptableinputstream;1"]
    .getService(Components.interfaces.nsIScriptableInputStream);
  // http://lxr.mozilla.org/mozilla/source/intl/uconv/idl/nsIScriptableUConv.idl
  var unicodeConverter = Components
    .classes["@mozilla.org/intl/scriptableunicodeconverter"]
    .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
  unicodeConverter.charset = charset;

  var channel=ioService.newChannelFromURI(aURL);
  var input=channel.open();
  scriptableStream.init(input);
  var str=scriptableStream.read(input.available());
  scriptableStream.close();
  input.close();

  try {
    return unicodeConverter.ConvertToUnicode(str);
  } catch( e ) {
    return str;
  }
}
TailsNS.getContentDir = function() {
  var reg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
      .getService(Components.interfaces.nsIChromeRegistry);

  var ioSvc = Components.classes["@mozilla.org/network/io-service;1"]
      .getService(Components.interfaces.nsIIOService);

  var proto = Components.classes["@mozilla.org/network/protocol;1?name=file"]
      .getService(Components.interfaces.nsIFileProtocolHandler);

  var chromeURL = ioSvc.newURI("chrome://tails/content", null, null);
  var fileURL = reg.convertChromeURL(chromeURL);
  var file = proto.getFileFromURLSpec(fileURL.spec).parent;

  return file
}
TailsNS.getTempFile = function() {
  var file = Components.classes["@mozilla.org/file/directory_service;1"]
        .getService(Components.interfaces.nsIProperties)
        .get("TmpD", Components.interfaces.nsILocalFile);

  file.append("tails_" + new Date().getTime());

  return file;
}
TailsNS.getWriteStream = function(file) {
  var stream = Components.classes["@mozilla.org/network/file-output-stream;1"]
    .createInstance(Components.interfaces.nsIFileOutputStream);

  stream.init(file, 0x02 | 0x08 | 0x20, 420, -1);

  return stream;
}
TailsNS.getLocalFile = function(directory,file) {
  var f = Components.classes["@mozilla.org/file/local;1"]
      .createInstance(Components.interfaces.nsILocalFile);
  f.initWithPath(directory);
  f.append(file);
  return f;
}
/* returns the contents of the given local file */
TailsNS.getContentsForLocalDirectoryAndFile = function(directory, file) {
  return TailsNS.getContents(TailsNS.getURI(TailsNS.getLocalFile(directory, file)));
}
/* parse an XML document and get a DOM back */
TailsNS.parseDOM = function(contents, mimeType) {
  var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
      .createInstance(Components.interfaces.nsIDOMParser);
  return domParser.parseFromString(contents, mimeType);
}
/* returns a URI for the given file */
TailsNS.getURI = function(file) {
  return Components.classes["@mozilla.org/network/io-service;1"]
      .getService(Components.interfaces.nsIIOService)
      .newFileURI(file);
}



TailsNS.listen = function(source, event, listener, opt_capture) {
  Components.lookupMethod(source, "addEventListener").apply(
    source, [event, listener, opt_capture]);
}
TailsNS.unlisten = function(source, event, listener, opt_capture) {
  Components.lookupMethod(source, "removeEventListener").apply(
    source, [event, listener, opt_capture]);
}
TailsNS.listener = function(obj,meth) {
  if (!obj[meth]) {
    throw "method '" + meth + "' does not exist on object '" + obj + "'";
  }

  var staticArgs = Array.prototype.splice.call(arguments, 2, arguments.length);

  var func = function() {
    // make a copy of staticArgs (don't modify it because it gets reused for
    // every invocation).
    var args = staticArgs.concat();

    // add all the new arguments
    for (var i = 0; i < arguments.length; i++) {
      args.push(arguments[i]);
    }

    // invoke the original function with the correct this obj and the combined
    // list of static and dynamic arguments.
    return obj[meth].apply(obj, args);
  };
  if (!obj.__listeners) obj.__listeners = {};
  obj.__listeners[meth] = func;
  return func;
}
function Tails_listen(source, event, listener, opt_capture) {
  TailsNS.listen(source, event, listener, opt_capture);
}
function Tails_unlisten(source, event, listener, opt_capture) {
  TailsNS.unlisten(source, event, listener, opt_capture);
}
function Tails_hitch(obj, meth) {
  return TailsNS.listener(obj,meth);
}


function Tails_extendObject(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

TailsNS.getMessage = function(key, msgArgs) {
  return msgArgs 
      ? $$('tails_strings').getFormattedString(key, msgArgs)
      : $$('tails_strings').getString(key);
}

TailsNS.createLoadListener = function(target, func) {
  var wrapper = function() {
    target.removeEventListener("load", wrapper, true);
    func();
  };
  target.addEventListener("load", wrapper, true);
}

TailsNS.extendObject = function(obj, source) {
  for (var property in source) {
    obj[property] = source[property];
  }
  return obj;
};

function $$(node) {
  return document.getElementById(node);
}
